<?php
/**
 * note that all resources are relative of the DOCUMENT_ROOT constant
 */
class DigFile_Model_Resource {
    public $id;
    public $name;
    public $namespace;
    public $size;
    public $path;

    protected $_pathToTrash = '/trash';

    protected $_modelMaps = array(
            'pdf'   => 'DigFile_Model_Pdf',
            'php'   => 'DigFile_Model_Php',
            'phtml' => 'DigFile_Model_Php',
            'html'  => 'DigFile_Model_Html',
            'htm'   => 'DigFile_Model_Html',
            'zip'   => 'DigFile_Model_Zip',
            'swf'   => 'DigFile_Model_Flash',
            'flv'   => 'DigFile_Model_Flash',
            'png'   => 'DigFile_Model_Image',
            'gif'   => 'DigFile_Model_Image',
            'jpg'   => 'DigFile_Model_Image',
            'tiff'  => 'DigFile_Model_Image',
            'jpeg'  => 'DigFile_Model_Image',
            'avi'   => 'DigFile_Model_Video',
            'mpeg'   => 'DigFile_Model_Video',
            'mpg'   => 'DigFile_Model_Video',
            'wmv'   => 'DigFile_Model_Video',
            'mov'  => 'DigFile_Model_Video',
    );

    protected $_hiddenFiles = array('svn');

    public function  __construct($file = null) {
        if($file != null) {
            $this->name = basename($file);
            $this->namespace = get_class($this);
            if(dirname($file) != "\\" && dirname($file) != "/") {
                $this->path = dirname($file);
            }
        }
    }

    public static function factory($filename) {
        $model = new self();
        if(is_dir($model->rootPath($filename))) {
            return new DigFile_Model_Symlink($filename);
        } else {
            $className = $model->getModelByFilename($filename);
            if($className) {
                return new $className($filename);
            }
        }
    }

    /**
     * inspects the namespace and determines which controller should
     * handle the file
     */
    public function controller() {
        $controller = array_pop(explode('_', $this->namespace));
        $filter = new Zend_Filter();
        $filter->addFilter(new Zend_Filter_Word_CamelCaseToDash())
                ->addFilter(new Zend_Filter_StringToLower());
        return $filter->filter($controller);
    }

    public function toArray() {
        return array(
            'name'  => $this->name,
            'namespace' => $this->namespace,
            'path'      => $this->filepath()
        );
    }

    public function isFile() {
        if(!$this->exists()) {
            return false;
        }
        return $this->info()->isFile();
    }

    public function isDir() {
        if(!$this->exists()) {
            return false;
        }
        return $this->info()->isDir();
    }

    public function isHidden() {
        return in_array($this->getExtension(), $this->_hiddenFiles);
    }

    public function isImage() {
        if(!$this->exists()) {
            return false;
        }
        if(getimagesize($this->_rootPath())) {
            return true;
        }
    }

    public function getModelByFilename($file) {
        $extension = $this->getExtension($file);
        if(array_key_exists($extension, $this->_modelMaps)) {
            return $this->_modelMaps[$extension];
        } else {
            return 'DigFile_Model_File';
        }
    }

    public function getExtension($file = null) {
        if($file == null) {
            $file = $this->name;
        }
        return array_pop(explode('.', $file));
    }

    public function exists() {
        return file_exists($this->rootPath());
    }

    public function rename($newName) {
        if($this->exists()) {
            //echo dirname($this->rootPath()) . $newName; die();
            rename($this->rootPath(), dirname($this->rootPath()) . '/' . $newName);
            $this->name = $newName;
        }
    }

    public function move(DigFile_Model_Symlink $folder, $append = null) {
        if($this->exists()) {
            // we do this to append the timestamp onto discarded files
            $newName = $this->name;
            if($append != null) {
                $newName .= '.' . $append;
            }
            rename($this->rootPath(), $folder->rootPath() . '/' . $newName);
            $this->path = $folder->filepath();
        }
    }

    public function discard() {
        $this->move($this->trash(), time());
    }

    public function trash() {
        return new DigFile_Model_Symlink($this->_pathToTrash);
    }

    public function hasChildren() {
        // a default resource does not have children (they are files)
        return false;
    }

    /**
     * returns the spl file info object for the current filepath
     *
     * @return SplFileInfo
     */
    public function info() {
        if($this->exists()) {
            $resource = new self();
            return new SplFileInfo($this->rootPath());
        } else {
            return false;
        }
    }

    public function filepath() {
        return $this->path . '/' . $this->name;
    }

    /**
     * The size method returns the size of the current file
     *
     * You can optionally specify the unit to return. The options are 'mb','kb' and 'b'
     * 
     * @param string $unit
     * @return float
     */
    public function size($unit = 'kb') {
        $size = $this->info()->getSize();
        $units = array(
            'mb'    => 1000000,
            'kb'    => 1000,
            'b'     => 1
        );
        $factor = $units[ strtolower($unit)];
        return $size / $factor;
    }

    public function rootPath($filepath = null) {
        if($filepath == null) {
            $filepath = $this->filepath();
        }
        if(! empty ($filepath)) {
            $filepath = DOCUMENT_ROOT . '/' . $filepath;
        }
        return str_replace('//', '/', $filepath);
    }

    public function  __toString() {
        return $this->filepath();
    }
}
?>